package com.wtwd.campus.netty;

import com.wtwd.campus.encryptnetty.EncryptChannelMap;
import com.wtwd.campus.receiver.Receiver;
import com.wtwd.campus.receiver.ReceiverFactory;
import com.wtwd.campus.thread.NamedThreadFactory;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 处理连接与通讯
 */
public class ServerHandler extends ChannelInboundHandlerAdapter {
    private final static Logger logger = LoggerFactory.getLogger(ServerHandler.class);


    private static final ExecutorService executor = Executors.newFixedThreadPool(4, new NamedThreadFactory("analysisMessage"));

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIp = insocket.getAddress().getHostAddress();
        System.out.println("收到客户端[ip:" + clientIp + "]连接");
        Channel channel = ctx.channel();
        logger.info("[channel id:{} device addr:{}] msg:{}", channel.id(), channel.remoteAddress());
    }


    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 1.msg转为实际操作实体类  2.保存通道或者刷新通道  3.处理消息  4.写入ctx作为回复   5.写入异常则关闭通道；成功则保存通道
        logger.info("[channel id:{} 解析到指令:={}", ctx.channel().id(), msg.toString());
        executor.submit(
                () -> {
                    Receiver receiver = ReceiverFactory.createReceiver(String.valueOf(msg));
                    logger.info("[channel id:{}] 当前线程: " + ctx.channel().id() + Thread.currentThread().getName() + "处理上报消息: " + msg);
                    if (receiver != null) {
                        //解析数据，并把数据往后端传
                        try {
                            String command = msg.toString();
                            String[] split = command.split(",");
                            String imei = split[1];
                            //保存或者刷新通道
                            ChannelHandler.addOrRefreshChannel(imei, ctx.channel());
                            receiver.parseMessage(String.valueOf(msg));
                        } catch (Exception e) {
                            logger.error("[channel id:{}] 数据解析异常[{}]", ctx.channel().id(), e.getMessage());
                        } finally {
                            ReferenceCountUtil.release(msg);
                        }
                    }
                }
        );
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ChannelHandler.closeChannel(ctx.channel());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        logger.info("[channel id:{}] imei={},设备主动断开连接，关闭通道", ctx.channel().id(), ChannelMap.getKey(ctx.channel()));
        ChannelHandler.closeChannel(ctx.channel());
    }

}